#include <myheader_c_plus.h>
#include <set>
#include <map>
using std::endl;
using std::cout;
using std::vector;
using std::istringstream;
using std::ostream;
using std::set;
using std::map;
using std::shared_ptr;
using std::make_shared;
using std::string;
using std::ifstream;
class QuaryResult;
class TextQuary;
class QuaryResult{
public:
    //构造函数
    QuaryResult(string word,shared_ptr<vector<string>> lines, shared_ptr<set<int>> lineno)
    :_word(word)
    ,_lines(lines)
    ,_lineno(lineno)
    {

    }


friend ostream & operator<<(ostream & os, const QuaryResult & rhs);

private:
    //保存查询的单词
    string _word;
    //指向保存行的vector
    shared_ptr<vector<string>> _lines;
    //指向保存行号的set
    shared_ptr<set<int>> _lineno;
};
ostream & operator<<(ostream & os, const QuaryResult & rhs){
        os << rhs._word << " occors " << rhs._lineno->size() << " times" << endl;
        for(auto ele : *(rhs._lineno)){
            os <<"( rhs.lines " << ele << " )" << ((*rhs._lines))[ele - 1] << endl;

        }
        return os;
}
//该类用于将传入的文件进行保存
class TextQuary{
public:
    //构造函数
    TextQuary(ifstream & fs)
    {
        //读取文件至vector
        if(fs.good()){
            string line;
            int lineNo = 0;
            while(getline(fs, line)){
                ++lineNo;
                _lines->push_back(line);
                cout << "23: _line[lineNo]:  " << (*_lines)[lineNo - 1] << endl;
                //处理每行的单词
                string word;
                istringstream is(line);
                while(is >> word){
                    cout << "28: word:  " << word << endl;
                    auto it = word_lineNo.find(word);
                    //判断是否出现过这个单词
                    if(it != word_lineNo.end()){
                        //说明找到了,则将再次出现的单词行插入到对应单词的lineNo里面
                        it->second->insert(lineNo);
                        continue;
                    }
                    if(it == word_lineNo.end()){
                        shared_ptr<set<int>> _lineNo = make_shared<set<int>>();
                        _lineNo->insert(lineNo);
                        word_lineNo.insert(std::make_pair(word,_lineNo));
                    }
                }
            }
        }
    }
    //查询vv
    QuaryResult quary(string word) {
        static shared_ptr<set<int>> nodata(new set<int>);
        auto it = word_lineNo.find(word);
        if(it != word_lineNo.end()){
            QuaryResult qr(word, _lines, it->second);
            return qr;
        }
         QuaryResult qrnodata(word, _lines, nodata);
         return qrnodata;
    }



private:
    //用于保存传入文件的所有行
    shared_ptr<vector<string>> _lines = make_shared<vector<string>>();
    //map用于保存
    map<string, shared_ptr<set<int>>> word_lineNo;
};
class Quary;
class Quary_base{
    friend class Quary;
    virtual  string rep() = 0;
    virtual QuaryResult eval(TextQuary & tq) = 0;

};

//用于保存查找给定单词
class WordQuary : public Quary_base{
    friend class Quary;
    WordQuary(string quary_word)
    :_quary_word(quary_word)
    {

    }
    QuaryResult eval(TextQuary & tq) override{
        return tq.quary(_quary_word);

    }
    string rep() override{
        return _quary_word;
    }

    string _quary_word;


};
class Quary{
public:
    friend Quary operator~(const Quary &q);
    //构造函数,构建一个新的WordQuary
    Quary(const string & word)
    :q(new WordQuary(word))
    {
        
    
    }
    QuaryResult eval (TextQuary & t) const{
        return q->eval(t);
    }
    string rep() const{
        return q->rep();
    }
    


private:
    Quary(shared_ptr<Quary_base> quary)
    :q(quary)
    {

    }
    shared_ptr<Quary_base> q;
};
//Quary输出运算符重载
ostream & operator<<(ostream os, const Quary & rhs){
    return os << rhs.rep();
}
class NotQuary : public Quary_base{
    friend Quary operator~(const Quary &q);
    NotQuary(const Quary & q)
    :quary(q)
    {

    }
    string rep()override{
        return "~(" + quary.rep() + ")" ;
    }
/*
 *     QuaryResult eval(TextQuary & tq)override{
 *         cout << "eval" << endl;
 *
 *     }
 */
    Quary quary;
};
/*
 * Quary operator~(const Quary &q){
 *     return shared_ptr<Quary_base>(new NotQuary(q));
 * }
 */
class BinaryQuary : public Quary_base{
protected:
    BinaryQuary(const Quary & lhs, const Quary  & rhs, string s)
    :_lhs(lhs)
    ,_rhs(rhs)
    ,opSym(s)
    {

    }
    //抽象类，不定义eval
    string rep()override{
        return "(" + _lhs.rep() + " " + opSym + " " + _rhs.rep() + ")";
    }
    Quary _lhs, _rhs;
    string opSym;
};
class AndQuary : public BinaryQuary{
    AndQuary(const Quary & left, const Quary & right)
    :BinaryQuary(left, right,"&")
    {

    }
/*
 *     QuaryResult eval(TextQuary & tq)override{
 *
 *     }
 */
};
int main(int argc, char *argv[])
{
    /*
     * ifstream fs("text.txt");
     * TextQuary tq(fs);
     * QuaryResult qr = tq.quary("girl");
     * cout << qr;
     */



    return 0;
}

